﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NasuTek.Shion.Agent;
using System.Threading;
using System.IO;
using Skybound.Gecko;
using System.Xml.Serialization;
using System.Xml;
using System.Diagnostics;
using NasuTek.Shion.Extencibility;
using System.Resources;
using System.Text.RegularExpressions;

namespace NasuTek.Shion
{
    public partial class Form1
    {
        List<string> Bans = new List<string>();

        void Form1_OnRawMessage(object sender, IrcEventArgs e)
        {
            if (e.Data.ReplyCode == ReplyCode.WhoIsUser)
            {
                em.WhoIsData.WhoIsUser = e.Data.RawMessage.Remove(0, e.Data.RawMessageArray[0].Length + e.Data.RawMessageArray[1].Length + e.Data.RawMessageArray[2].Length + e.Data.RawMessageArray[3].Length + 4);
            }
            else if (e.Data.ReplyCode == ReplyCode.WhoIsServer)
            {
                em.WhoIsData.WhoIsServer = e.Data.RawMessage.Remove(0, e.Data.RawMessageArray[0].Length + e.Data.RawMessageArray[1].Length + e.Data.RawMessageArray[2].Length + e.Data.RawMessageArray[3].Length + 4);
            }
            else if (e.Data.ReplyCode == ReplyCode.WhoIsOperator)
            {
                em.WhoIsData.WhoIsOperator = e.Data.RawMessage.Remove(0, e.Data.RawMessageArray[0].Length + e.Data.RawMessageArray[1].Length + e.Data.RawMessageArray[2].Length + e.Data.RawMessageArray[3].Length + 4);
            }
            else if (e.Data.ReplyCode == ReplyCode.WhoIsIdle)
            {
                em.WhoIsData.WhoIsIdle = e.Data.RawMessage.Remove(0, e.Data.RawMessageArray[0].Length + e.Data.RawMessageArray[1].Length + e.Data.RawMessageArray[2].Length + e.Data.RawMessageArray[3].Length + 4);
            }
            else if (e.Data.ReplyCode == ReplyCode.WhoIsChannels)
            {
                em.WhoIsData.WhoIsChannels = e.Data.RawMessage.Remove(0, e.Data.RawMessageArray[0].Length + e.Data.RawMessageArray[1].Length + e.Data.RawMessageArray[2].Length + e.Data.RawMessageArray[3].Length + 4);
            }
            else if (e.Data.ReplyCode == ReplyCode.EndOfWhoIs)
            {

                if (em.WhoIsData.WhoIsUser != null)
                {
                    if (em.WhoIsData.Handled == false)
                    {
                        Invoke(new Action(delegate
                        {
                            new WhoIs(em.WhoIsData.WhoIsUser, em.WhoIsData.WhoIsServer, em.WhoIsData.WhoIsOperator, em.WhoIsData.WhoIsIdle, em.WhoIsData.WhoIsChannels).ShowDialog();
                            em.WhoIsData.CleanUpWhoIsData();
                        }));
                    }
                    else { em.WhoIsHandled(this); }
                }
                else
                {
                    if (em.WhoIsData.Handled == false)
                    {
                        Invoke(new Action(delegate
                        {
                            new WhoIs("This User is not Online", "", "", "", "").ShowDialog();
                        }));
                    }
                    else { em.WhoIsHandled(this); }
                }
            }
            else if (e.Data.ReplyCode == ReplyCode.ChannelModeIs)
            {
                if (ChannelModes[e.Data.Server].ContainsKey(e.Data.Channel.ToLower()))
                {
                    ChannelModes[e.Data.Server][e.Data.Channel.ToLower()] = e.Data.RawMessageArray[4];
                    if (openingInspector == true)
                    {                        
                        Form1.Clients[em.activeServer].Ban(em.activeChannel);
                    }
                }
            }
            else if (e.Data.ReplyCode == ReplyCode.BanList)
            {
                Bans.Add(e.Data.RawMessageArray[4]); //TODO: e.Data.RawMessageArray[5] shows who banned
            }
            else if (e.Data.ReplyCode == ReplyCode.EndOfBanList)
            {
                if (openingInspector == true)
                {
                    openingInspector = false;
                    Invoke(new Action(delegate { new Inspector(e.Data.Channel.ToLower(), e.Data.Server, Topics[e.Data.Server][e.Data.Channel.ToLower()]).Show(panel, WeifenLuo.WinFormsUI.Docking.DockState.DockRight); }));
                }
                else
                {
                    Invoke(new Action(delegate { new Bans(Bans).ShowDialog(); }));
                }
                Bans.Clear();
            }
            else if (e.Data.ReplyCode == ReplyCode.List)
            {
                WriteToChannelText("echo►" + e.Data.RawMessage + "►" + DateTime.Now.ToShortTimeString(), "console", e.Data.Server);
            }
            else if (e.Data.ReplyCode == ReplyCode.ListEnd)
            {
                WriteToChannelText("echo►End of /LIST" + "►" + DateTime.Now.ToShortTimeString(), "console", e.Data.Server);
            }
            if(DebuggingServers.Contains(e.Data.Server))
            {
                Raw.Add("echo►[" + e.Data.Server + "] " + e.Data.RawMessage + "►" + DateTime.Now.ToShortTimeString());
                if (em.activeChannel == "debug")
                {
                    RefreshWindow();
                }
            }
            foreach (KeyValuePair<string,OnRaw> i in em.OnRaw)
            {
                i.Value.Execute(e, em);
            }
        }

        void Form1_OnTopic(object sender, TopicEventArgs e)
        {
            Topics[e.Data.Server][e.Channel.ToLower()] = e.Topic;
        }

        void Form1_OnWriteLine(object sender, WriteLineEventArgs e)
        {
            string[] split = e.Line.Split(' ');
            if (split[0] == "PRIVMSG")
            {
                string where = split[1];
                split[0] = "";
                split[1] = "";
                string p = String.Join(" ", split).Remove(0, 3);
                if (p.Contains("\x1" + "ACTION"))
                {
                    p = p.Replace("\x1" + "ACTION", "");
                    p = p.Replace("\x1", "");
                    List<string> i = new List<string>(ChannelText[em.activeServer][em.activeChannel]);
                    i.Add("ownaction►" + Clients[em.activeServer].Nickname + ":" + where + "►" + p + "►" + DateTime.Now.ToShortTimeString());
                    ChannelText[em.activeServer][em.activeChannel] = i.ToArray();
                    RefreshWindow();
                }
                else
                {
                    List<string> i = new List<string>(ChannelText[em.activeServer][em.activeChannel]);
                    i.Add("ownmessage►" + Clients[em.activeServer].Nickname + ":" + where + "►" + String.Join(" ", split).Remove(0, 3) + "►" + DateTime.Now.ToShortTimeString());
                    ChannelText[em.activeServer][em.activeChannel] = i.ToArray();
                    RefreshWindow();
                }
            }
            else if (split[0] == "NOTICE")
            {
                string where = split[1];
                split[0] = "";
                split[1] = "";

                List<string> i = new List<string>(ChannelText[em.activeServer][em.activeChannel]);
                i.Add("ownnotice►" + Clients[em.activeServer].Nickname + ":" + where + "►" + String.Join(" ", split).Remove(0, 3) + "►" + DateTime.Now.ToShortTimeString());
                ChannelText[em.activeServer][em.activeChannel] = i.ToArray();
                RefreshWindow();
            }
        }

        void Form1_OnModeChange(object sender, IrcEventArgs e)
        {
            if (!exiting)
            {
                if (e.Data.Channel != null)
                {
                    string id = e.Data.RawMessage.Substring(e.Data.RawMessageArray[0].Length + e.Data.RawMessageArray[1].Length + e.Data.RawMessageArray[2].Length + e.Data.RawMessageArray[3].Length);
                    WriteToChannelText("modechange►" + e.Data.Nick + "►" + id + "►" + DateTime.Now.ToShortTimeString(), e.Data.Channel, e.Data.Server);
                    Invoke(new Action(delegate { ServerExplorer.Nodes[e.Data.Server].Nodes[e.Data.Channel.ToLower()].ForeColor = Color.Blue; }));
                }
            }
        }

        void Form1_OnQuit(object sender, QuitEventArgs e)
        {
            if (!exiting)
            {
                int y = 0;
                foreach (KeyValuePair<string, string[]> v in NamesList[e.Data.Server])
                {
                    foreach (string x in v.Value)
                    {
                        if (x.Contains(e.Who))
                        {
                            NamesList[e.Data.Server][v.Key][y] = "";
                            if (Ops[e.Data.Server][v.Key].Contains(e.Who)) { Ops[e.Data.Server][v.Key].Remove(e.Who); }
                            if (HalfOps[e.Data.Server][v.Key].Contains(e.Who)) { HalfOps[e.Data.Server][v.Key].Remove(e.Who); }
                            if (Vops[e.Data.Server][v.Key].Contains(e.Who)) { Vops[e.Data.Server][v.Key].Remove(e.Who); }
                            if ((em.activeServer == e.Data.Server) && (em.activeChannel == v.Key)) { RefreshWindow();
                            Invoke(new Action(delegate { NickList.Items.RemoveByKey(e.Who); }));
                            }
                            WriteToChannelText("quit►" + e.Who + "►" + e.QuitMessage + "►" + e.Data.Host + "►" + DateTime.Now.ToShortTimeString(), v.Key, e.Data.Server);
                            break;
                        }
                        y++;
                    }
                    y = 0;
                }
                CleanNamesList(e.Data.Server, new List<string>());
                if (em.HostMasks[e.Data.Server].Contains(e.Data.From) == true)
                {
                    em.HostMasks[e.Data.Server].Remove(e.Data.From);
                }
            }
        }

        void Form1_OnError(object sender, NasuTek.Shion.Agent.ErrorEventArgs e)
        {
            if (!exiting)
            {
                WriteToChannelText("error►" + "(" + e.Data.Server + ") " + e.ErrorMessage + "►" + DateTime.Now.ToShortTimeString(), em.activeChannel, em.activeServer);
            }
        }

        void Form1_OnQueryMessage(object sender, IrcEventArgs e)
        {
            if (!exiting)
            {
                if (ChannelText[e.Data.Server].ContainsKey(e.Data.Nick.ToLower()))
                {
                    Ignore ignore;
                    if (config.GetServer(e.Data.Server) != null)
                    {
                        ignore = config.GetServer(e.Data.Server).GetIgnore(e.Data.From);
                    }
                    else { ignore = null; }
                    bool ignored = false;

                    if (ignore != null)
                    {
                        ignored = ignore.IgnorePrivateMessages;
                    }
                    if (ignored != true)
                    {
                        WriteToChannelText("message►" + e.Data.Nick + "►" + e.Data.Message + "►" + DateTime.Now.ToShortTimeString(), e.Data.Nick, e.Data.Server);
                    }
                }
                else
                {
                    Ignore ignore = config.GetServer(e.Data.Server).GetIgnore(e.Data.From);
                    bool ignored = false;

                    if (ignore != null)
                    {
                        ignored = ignore.IgnorePrivateMessages;
                    }
                    if (ignored != true)
                    {
                        ChannelText[e.Data.Server].Add(e.Data.Nick.ToLower(), new string[] { });
                        Invoke(new Action(delegate
                        {
                            ServerExplorer.Nodes[e.Data.Server].Nodes.Add(e.Data.Nick.ToLower(), e.Data.Nick.ToLower(), "Query", "Query");
                            SetActiveWindow(e.Data.Server, e.Data.Nick.ToLower());
                        }));

                        WriteToChannelText("message►" + e.Data.Nick + "►" + e.Data.Message + "►" + DateTime.Now.ToShortTimeString(), e.Data.Nick, e.Data.Server);
                    }
                }
            }
        }

        void Form1_OnQueryNotice(object sender, IrcEventArgs e)
        {
            if (!exiting)
            {
                Ignore ignore;
                if (config.GetServer(e.Data.Server) != null)
                {
                    ignore = config.GetServer(e.Data.Server).GetIgnore(e.Data.From);
                }
                else { ignore = null; }
                bool ignored = false;

                if (ignore != null)
                {
                    ignored = ignore.IgnoreNotices;
                }
                if (ignored != true)
                {
                    WriteToChannelText("notice►" + e.Data.Nick + "►" + e.Data.Message + "►" + DateTime.Now.ToShortTimeString(), "console", e.Data.Server);
                }
            }
        }
        

        void Form1_OnMotd(object sender, MotdEventArgs e)
        {
            if (!exiting)
            {
                WriteToChannelText("echo►" + e.MotdMessage + "►" + DateTime.Now.ToShortTimeString(), "console", e.Data.Server);
            }
        }

        void Form1_OnPart(object sender, PartEventArgs e)
        {
            if (!exiting)
            {
                try
                {
                    Ignore ignore;
                    if (config.GetServer(e.Data.Server) != null)
                    {
                        ignore = config.GetServer(e.Data.Server).GetIgnore(e.Data.From);
                    }
                    else { ignore = null; }
                    bool ignored = false;

                    if (ignore != null)
                    {
                        ignored = ignore.IgnoreJoinAndPart;
                    }
                    if (ignored != true)
                    {
                        WriteToChannelText("part►" + e.Who + "►" + e.Channel + "►" + DateTime.Now.ToShortTimeString(), e.Channel, e.Data.Server);
                        List<string> s = new List<string>(NamesList[e.Data.Server][e.Channel.ToLower()]);
                        s.Remove(e.Who);
                        NamesList[e.Data.Server][e.Channel.ToLower()] = s.ToArray();
                        Ops[e.Data.Server][e.Channel.ToLower()].Remove(e.Who);
                        HalfOps[e.Data.Server][e.Channel.ToLower()].Remove(e.Who);
                        Vops[e.Data.Server][e.Channel.ToLower()].Remove(e.Who);
                        if ((em.activeChannel == e.Data.Channel.ToLower()) && (em.activeServer == e.Data.Server))
                        {
                            Invoke(new Action(delegate { NickList.Items.RemoveByKey(e.Who); }));
                        }
                    }
                    Invoke(new Action(delegate { ServerExplorer.Nodes[e.Data.Server].Nodes[e.Data.Channel.ToLower()].ForeColor = Color.Blue; }));
                }
                catch (KeyNotFoundException) { }

            }
        }

        void Form1_OnDevoice(object sender, DevoiceEventArgs e)
        {
            if (!exiting)
            {
                ModeOperation("-v", e.Whom, e.Channel, e.Data.Server);
            }
        }

        void Form1_OnVoice(object sender, VoiceEventArgs e)
        {
            if (!exiting)
            {
                ModeOperation("+v", e.Whom, e.Channel, e.Data.Server);
            }
        }

        void Form1_OnDehalfop(object sender, DehalfopEventArgs e)
        {
            if (!exiting)
            {
                ModeOperation("-h", e.Whom, e.Channel, e.Data.Server);
            }
        }

        void Form1_OnHalfop(object sender, HalfopEventArgs e)
        {
            if (!exiting)
            {
                ModeOperation("+h", e.Whom, e.Channel, e.Data.Server);
            }
        }

        void Form1_OnDeop(object sender, DeopEventArgs e)
        {
            if (!exiting)
            {
                ModeOperation("-o", e.Whom, e.Channel, e.Data.Server);
            }
        }

        void Form1_OnOp(object sender, OpEventArgs e)
        {
            if (!exiting)
            {
                ModeOperation("+o", e.Whom, e.Channel, e.Data.Server);
            }
        }

        void Form1_OnUnban(object sender, UnbanEventArgs e)
        {
            if (!exiting)
            {
                WriteToChannelText("unbanned►" + e.Who + "►" + e.Hostmask + "►" + DateTime.Now.ToShortTimeString(), e.Channel, e.Data.Server);
            }
        }

        void Form1_OnBan(object sender, BanEventArgs e)
        {
            if (!exiting)
            {
                WriteToChannelText("banned►" + e.Who + "►" + e.Hostmask + "►" + DateTime.Now.ToShortTimeString(), e.Channel, e.Data.Server);
            }
        }

        void Form1_OnKick(object sender, KickEventArgs e)
        {
            if (!exiting)
            {
                WriteToChannelText("kicked►" + e.Who + "►" + e.Whom + "►" + e.KickReason + "►" + DateTime.Now.ToShortTimeString(), e.Channel, e.Data.Server);
/*              if (e.Whom == Clients[e.Data.Server].Nickname)
                {
                    Invoke(new Action(delegate
                    {
                        treeView1.Nodes[e.Data.Server].Nodes.RemoveByKey(e.Channel.ToLower());
                    }));
                }
 * 
 */
                Invoke(new Action(delegate { ServerExplorer.Nodes[e.Data.Server].Nodes[e.Data.Channel.ToLower()].ForeColor = Color.Blue; }));
            }
        }

        void Form1_DisconnectedHandle(object sender, string e)
        {
            if (!exiting)
            {
                Invoke(new Action(delegate
                {
                    ServerExplorer.Nodes.RemoveByKey(e);
                    Clients.Remove(e);
                    ChannelText.Remove(e);
                    NamesList.Remove(e);
                    Ops.Remove(e);
                    HalfOps.Remove(e);
                    Vops.Remove(e);
                    Topics.Remove(e);
                    ChannelModes.Remove(e);
                    em.HostMasks.Remove(e);
                }));
            }
        }

        void Form1_OnNickChange(object sender, NickChangeEventArgs e)
        {
            if (!exiting)
            {
                int y = 0;
                foreach (KeyValuePair<string, string[]> v in NamesList[e.Data.Server])
                {
                    foreach (string x in v.Value)
                    {
                        if (x.Contains(e.OldNickname))
                        {
                            NamesList[e.Data.Server][v.Key][y] = x.Replace(e.OldNickname, e.NewNickname);
                            List<string> i = new List<string>(ChannelText[e.Data.Server][v.Key]);
                            i.Add("nickchange►" + e.OldNickname + "►" + e.NewNickname + "►" + DateTime.Now.ToShortTimeString());
                            ChannelText[e.Data.Server][v.Key] = i.ToArray();
                            if (Ops[e.Data.Server][v.Key].Contains(e.OldNickname)) { Ops[e.Data.Server][v.Key].Remove(e.OldNickname); Ops[e.Data.Server][v.Key].Add(e.NewNickname); }
                            if (HalfOps[e.Data.Server][v.Key].Contains(e.OldNickname)) { HalfOps[e.Data.Server][v.Key].Remove(e.OldNickname); HalfOps[e.Data.Server][v.Key].Add(e.NewNickname); }
                            if (Vops[e.Data.Server][v.Key].Contains(e.OldNickname)) { Vops[e.Data.Server][v.Key].Remove(e.OldNickname); Vops[e.Data.Server][v.Key].Add(e.NewNickname); }
                            if (em.activeChannel == v.Key)
                            {
                                RefreshWindow();
                                ListViewItem item = new ListViewItem();
                                Invoke(new Action(delegate { NickList.Items.RemoveByKey(e.OldNickname); }));
                                Invoke(new Action(delegate { item.Name = e.NewNickname; }));
                                Invoke(new Action(delegate { item.Text = e.NewNickname; }));
                                Invoke(new Action(delegate { item.Group = NickList.Groups[GetHighestMode(e.NewNickname, e.Data.Server, v.Key)]; }));
                                Invoke(new Action(delegate { NickList.Items.Add(item); }));
                                Invoke(new Action(delegate { ServerExplorer.Nodes[e.Data.Server].Nodes[v.Key].ForeColor = Color.Blue; }));
                            }
                            break;
                        }
                        y++;
                    }
                    y = 0;
                }
                CleanNamesList(e.Data.Server, new List<string>());
            }
        }

        void Form1_OnChannelNotice(object sender, IrcEventArgs e)
        {
            if (!exiting)
            {
                Ignore ignore;
                if (config.GetServer(e.Data.Server) != null)
                {
                    ignore = config.GetServer(e.Data.Server).GetIgnore(e.Data.From);
                }
                else { ignore = null; }
                bool ignored = false;

                if (ignore != null)
                {
                    ignored = ignore.IgnoreNotices;
                }
                if (ignored != true)
                {
                    if (Clients.ContainsKey(e.Data.Server))
                    {
                        WriteToChannelText("notice►" + e.Data.Nick + "►" + e.Data.Message + "►" + DateTime.Now.ToShortTimeString(), "console", e.Data.Server);
                        foreach (KeyValuePair<string, OnCommand> i in em.OnNotice)
                        {
                            Dictionary<string, string> d = new Dictionary<string, string>();
                            d.Add("raw", e.Data.RawMessage);
                            d.Add("nick", e.Data.Nick);
                            d.Add("channel", e.Data.Channel);
                            i.Value.Execute(e.Data.MessageArray, d, em, e);
                        }
                        Invoke(new Action(delegate { ServerExplorer.Nodes[e.Data.Server].Nodes[e.Data.Channel.ToLower()].ForeColor = Color.Red; }));
                    }
                }
            }
        }

        void Form1_OnTopicChange(object sender, TopicChangeEventArgs e)
        {
            if (!exiting)
            {
                Topics[e.Data.Server][e.Channel.ToLower()] = e.NewTopic;
                WriteToChannelText("topicchanged►" + e.Who + "►" + e.NewTopic + "►" + DateTime.Now.ToShortTimeString(), e.Channel, e.Data.Server);
            }
        }

        void Form1_OnNames(object sender, NamesEventArgs e)
        {
            if (!exiting)
            {
                List<string> s = new List<string>(NamesList[e.Data.Server][e.Channel.ToLower()]);
                foreach (string i in e.UserList)
                {
                    if (i != "")
                    {
                        string x = i;
                        x = i.Replace('~', '@').Replace('&', '@');
                        if (x.Contains('@')) Ops[e.Data.Server][e.Channel.ToLower()].Add(x.Replace("@", ""));
                        else if (x.Contains('%')) HalfOps[e.Data.Server][e.Channel.ToLower()].Add(x.Replace("%", ""));
                        else if (x.Contains('+')) Vops[e.Data.Server][e.Channel.ToLower()].Add(x.Replace("+", ""));
                        s.Add(x.Replace("@", "").Replace("%", "").Replace("+", ""));
                    }
                }
                NamesList[e.Data.Server][e.Channel.ToLower()] = s.ToArray();
                SetActiveWindow(e.Data.Server, e.Channel);
            }
        }

        void Form1_OnJoin(object sender, JoinEventArgs e)
        {
            if (!exiting)
            {
                try
                {
                    Ignore ignore;
                    if (config.GetServer(e.Data.Server) != null)
                    {
                        ignore = config.GetServer(e.Data.Server).GetIgnore(e.Data.From);
                    }
                    else { ignore = null; }

                    bool ignored = false;

                    if (ignore != null)
                    {
                        ignored = ignore.IgnoreJoinAndPart;
                    }
                    if (ignored != true)
                    {
                        List<string> s = new List<string>(NamesList[e.Data.Server][e.Channel.ToLower()]);
                        s.Add(e.Who);
                        NamesList[e.Data.Server][e.Channel.ToLower()] = s.ToArray();
                        WriteToChannelText("join►" + e.Who + "►" + e.Channel + "►" + e.Data.Host + "►" + DateTime.Now.ToShortTimeString(), e.Channel, e.Data.Server);
                        if ((e.Channel == em.activeChannel) && (e.Data.Server == em.activeServer))
                        {
                            Invoke(new Action(delegate { NickList.Items.Add(e.Who, e.Who, 0); }));
                        }
                        Invoke(new Action(delegate { ServerExplorer.Nodes[e.Data.Server].Nodes[e.Data.Channel.ToLower()].ForeColor = Color.Blue; }));
                    }
                    if (em.HostMasks[e.Data.Server].Contains(e.Data.From) == false)
                    {
                        em.HostMasks[e.Data.Server].Add(e.Data.From);
                    }
                }
                catch (KeyNotFoundException)
                {
                    Clients[e.Data.Server].RfcJoin(e.Channel);
                    Clients[e.Data.Server].RfcWho(e.Channel);
                    ChannelText[e.Data.Server].Add(e.Channel.ToLower(), new string[] { });
                    NamesList[e.Data.Server].Add(e.Channel.ToLower(), new string[] { });
                    Ops[e.Data.Server].Add(e.Channel.ToLower(), new List<string>());
                    HalfOps[e.Data.Server].Add(e.Channel.ToLower(), new List<string>());
                    Vops[e.Data.Server].Add(e.Channel.ToLower(), new List<string>());
                    Topics[e.Data.Server].Add(e.Channel.ToLower(), "");
                    ChannelModes[e.Data.Server].Add(e.Channel.ToLower(), "");
                    Invoke(new Action(delegate
                    {
                        ServerExplorer.Nodes[e.Data.Server].Nodes.Add(e.Channel.ToLower(), e.Channel.ToLower(), "Channel", "Channel");
                    }));
                    WriteToChannelText("join►" + e.Who + "►" + e.Channel + "►" + e.Data.Host + "►" + DateTime.Now.ToShortTimeString(), e.Channel, e.Data.Server);
                }
            }
        }

        void Form1_OnChannelAction(object sender, ActionEventArgs e)
        {
            if (!exiting)
            {
                Ignore ignore;
                if (config.GetServer(e.Data.Server) != null)
                {
                    ignore = config.GetServer(e.Data.Server).GetIgnore(e.Data.From);
                }
                else { ignore = null; }
                bool ignored = false;

                if (ignore != null)
                {
                    ignored = ignore.IgnorePublicMessages;
                }
                if (ignored != true)
                {
                    if (Clients.ContainsKey(e.Data.Server))
                    {
                        WriteToChannelText("action►" + e.Data.Nick + "►" + e.ActionMessage + "►" + DateTime.Now.ToShortTimeString(), e.Data.Channel, e.Data.Server);
                        foreach (KeyValuePair<string, OnCommand> i in em.OnAction)
                        {
                            Dictionary<string, string> d = new Dictionary<string, string>();
                            d.Add("raw", e.Data.RawMessage);
                            d.Add("nick", e.Data.Nick);
                            d.Add("channel", e.Data.Channel);
                            i.Value.Execute(e.ActionMessage.Split(' '), d, em, e);
                        }
                        Invoke(new Action(delegate { ServerExplorer.Nodes[e.Data.Server].Nodes[e.Data.Channel.ToLower()].ForeColor = Color.Red; }));
                    }
                }
            }
        }

        void Form1_OnChannelMessage(object sender, IrcEventArgs e)
        {
            if (!exiting)
            {
                Ignore ignore;
                if (config.GetServer(e.Data.Server) != null)
                {
                    ignore = config.GetServer(e.Data.Server).GetIgnore(e.Data.From);
                }
                else { ignore = null; }
                bool ignored = false;

                if (ignore != null)
                {
                    ignored = ignore.IgnorePublicMessages;
                }
                if (ignored != true)
                {
                    if (Clients.ContainsKey(e.Data.Server))
                    {
                        WriteToChannelText("message►" + e.Data.Nick + "►" + e.Data.Message + "►" + DateTime.Now.ToShortTimeString(), e.Data.Channel, e.Data.Server);

                        Dictionary<string, string> d = new Dictionary<string, string>();
                        d.Add("raw", e.Data.RawMessage);
                        d.Add("nick", e.Data.Nick);
                        d.Add("channel", e.Data.Channel);
                        d.Add("server", e.Data.Server);

                        foreach (KeyValuePair<string, OnCommand> i in em.OnMessage)
                        {
                            i.Value.Execute(e.Data.MessageArray, d, em, e);
                        }
                        Invoke(new Action(delegate { ServerExplorer.Nodes[e.Data.Server].Nodes[e.Data.Channel.ToLower()].ForeColor = Color.Red; }));
                    }
                }
            }
        }

        void Form1_OnWho(object sender, WhoEventArgs e)
        {
            if (em.HostMasks[e.Data.Server].Contains(e.Nick + "!" + e.Ident + "@" + e.Host) == false)
            {
                em.HostMasks[e.Data.Server].Add(e.Nick + "!" + e.Ident + "@" + e.Host);
            }
        }
    }
}